package Bilibili;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import util.PythonUtil;

import java.io.File;
import java.text.MessageFormat;

import static json.ParseJsonUtil.readFileContent;

/**
 * android客户端 app
 */
public class BilibiliUtilVideoAPP {

    // 视频下载位置
    private static final String videoDownloadPath = "D:\\阿里云盘下载\\309450488";
    // ffmpeg exe路径，如果配置了环境变量，只写名称即可，如果没有配置，就写全路径
    private static final String ffmpegExePath = "ffmpeg";

    public static void main(String[] args) throws Exception {
        // 每个视频归类存储
        String filepath = videoDownloadPath;
        File file = new File(filepath);
        if (!file.exists() || !file.isDirectory()) {
            System.out.println("请指定正确的目录");
            return;
        }

        // 根目录下获取所有视频
        File[] dirFiles = file.listFiles((dir, name) -> dir.isDirectory());
        if (dirFiles == null || dirFiles.length == 0) {
            System.out.println("不存在分P文件");
            return;
        }

        File targetFile = null;
        boolean init = true;
        for (File dirFile : dirFiles) {

            // 309450488\c_1009571376： entry.json danmaku.xml 80
            // 309450488\c_1009571376\80： audio.m4s index.json video.m4s
            File[] pFiles = dirFile.listFiles();

            // 视频信息文件 entry.json
            File partNameFile = null;
            String type_tag;
            File videoFile = null; // 视频文件
            File audioFile = null; // 音频文件

            for (File pFile : pFiles) {
                if (!pFile.isFile()) {
                    continue;
                }
                if (pFile.getName().endsWith("entry.json")) {
                    partNameFile = pFile;

                    String jsonString = readFileContent(partNameFile);
                    JSONObject jsonObject = JSON.parseObject(jsonString);

                    // 是否下载完成
                    Boolean is_completed = jsonObject.getBoolean("is_completed");

                    if (is_completed != null && is_completed) {
                        type_tag = jsonObject.getString("type_tag");
                        File videoDir = new File(dirFile, type_tag);

                        if (videoDir.isDirectory()) {
                            File[] files = videoDir.listFiles();
                            for (File item : files) {
                                if (item.isFile() && item.getName().equals("audio.m4s")) {
                                    audioFile = item;
                                }
                                if (item.isFile() && item.getName().equals("video.m4s")) {
                                    videoFile = item;
                                }
                            }
                        }

                        if (videoFile != null && audioFile != null) {
                            // 视频名称
                            String title = jsonObject.getString("title");
                            JSONObject page_data = jsonObject.getJSONObject("page_data");
                            int page = page_data.getIntValue("page");
                            String partTitle = page_data.getString("part");

                            // 如果视频输出文件已存在，executePythonScript方法会卡主
                            // cmdStr: ffmpeg -i D:\阿里云盘下载\309450488\c_1011123995\80\video.m4s -i D:\阿里云盘下载\309450488\c_1011123995\80\audio.m4s -codec copy D:\阿里云盘下载\309450488\java面试题：你印象最深刻的bug是什么？\(2)2.Mybatis 动态sql if标签判读需注意的4个问题.mp4
                            // 1.直接报错(文件名有空格)：stderr:[AVFormatContext @ 000001e1d9460cc0] Unable to choose an output format for 'D:\闃块噷浜戠洏涓嬭浇\309450488\java闈㈣瘯棰橈細浣犲嵃璞℃渶娣卞埢鐨刡ug鏄粈涔堬紵\(2)2.Mybatis'; use a standard extension for the filename or specify the format manually.
                            // 2.提示覆盖：already exists. Overwrite? [y/N]
                            /*targetFile = new File(file, title);
                            if (init) {
                                // 已存在同名目录处理，在文件夹名称后面+副本
                                while (true) {
                                    if (!targetFile.exists() || !targetFile.isDirectory()) {
                                        // 创建目录
                                        // targetFile.mkdir(); // 只能创建一层目录
                                        targetFile.mkdirs(); // 创建多层目录，包括创建必需但不存在的父目录
                                        break;
                                    }
                                    title += "-副本";
                                    targetFile = new File(file, title);
                                }
                                init = false;
                            }*/

                            // 复制到一个新的目录下
                            if (targetFile == null) {
                                targetFile = new File(file, title);
                                // 已存在同名目录处理，在文件夹名称后面+副本
                                while (true) {
                                    if (!targetFile.exists() || !targetFile.isDirectory()) {
                                        // 创建目录
                                        // targetFile.mkdir(); // 只能创建一层目录
                                        targetFile.mkdirs(); // 创建多层目录，包括创建必需但不存在的父目录
                                        break;
                                    }
                                    title += "-副本";
                                    targetFile = new File(file, title);
                                }
                            }

                            File dest = new File(targetFile, "(" + page + ")" + partTitle + ".mp4");
                            // 合并音视频
                            ffmpegMerge(videoFile.getAbsolutePath(), audioFile.getAbsolutePath(), dest.getAbsolutePath());

                        }
                    }

                    break;
                }
            }

        }

    }

    /**
     * java实现音视频的合并
     * https://blog.csdn.net/maziaotong/article/details/127863727
     * 使用 ffmpeg 来合并音频和视频文件 https://www.cnblogs.com/dragona/p/17206097.html
     *
     * @param videoFilePath 原视频路径
     * @param audioFilePath 原视频路径
     * @param desFilePath   合并后视频存放路径+视频名称
     */
    public static void ffmpegMerge(String videoFilePath, String audioFilePath, String desFilePath) {
        // ffmpeg -i 原视频路径 -i 原音频路径 -codec copy 合并后视频存放路径+视频名称

        // MessageFormat使用时对单引号的处理方式 https://blog.csdn.net/ShewMi/article/details/77790496
        // 当使用MessageFormat读取到的字符串中，单引号会被移除
        // 不管怎样，双单引号仅代表一对单引号，对于多出的不起作用的单引号（如三个以上单引号）是会被移除的
        // String cmdStr = MessageFormat.format("ffmpeg -i ''{0}'' -i ''{1}'' -codec copy ''{2}''", videoFilePath, audioFilePath, desFilePath);
        // 不能加单引号
        String cmdStr = MessageFormat.format("ffmpeg -i {0} -i {1} -codec copy {2}", videoFilePath, audioFilePath, desFilePath);
        System.out.println("cmdStr: " + cmdStr);
        // 文件名有空格会执行十八，数组的方法不会
        // PythonUtil.executeCmd(cmdStr);

        // 解释器
        String exe = ffmpegExePath;
        // 组合成一个字符串数组
        // String[] cmdArr = new String[]{exe, "-i", videoFilePath, "-i", audioFilePath, "-codec", "copy", desFilePath};
        String[] cmdArr = new String[]{exe, "-loglevel", "quiet", "-i", videoFilePath, "-i", audioFilePath, "-codec", "copy", desFilePath};

        PythonUtil.executePythonScript(cmdArr);

    }

}
